package com.csgc.camera.util

import android.annotation.TargetApi
import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.hardware.camera2.CameraAccessException
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraManager
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import androidx.annotation.RequiresApi
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import java.io.BufferedReader
import java.io.File
import java.io.FileInputStream
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStreamReader
import java.io.RandomAccessFile
import java.nio.channels.FileChannel
import java.util.Formatter


object CommonUtils {

    /**
     * 跳转到APP的设置页面
     */
    fun openAppSettingPanel(context: Context) {
        val intent = Intent()
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        intent.action = "android.settings.APPLICATION_DETAILS_SETTINGS"
        intent.data = Uri.fromParts("package", context.packageName, null)
        context.startActivity(intent)
    }



    /**
     * 读取assets本地json
     * @param fileName
     * @param context
     * @return
     */
    fun getAssetsJson(fileName: String?, context: Context): String {
        //将json数据变成字符串
        val stringBuilder = StringBuilder()
        try {
            //获取assets资源管理器
            val assetManager = context.assets
            //通过管理器打开文件并读取
            val bf = BufferedReader(
                InputStreamReader(
                    assetManager.open(fileName!!)
                )
            )
            var line: String?
            while (bf.readLine().also { line = it } != null) {
                stringBuilder.append(line)
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return stringBuilder.toString()
    }


    @OptIn(DelicateCoroutinesApi::class)
    fun countDownCoroutines(total:Int, onTick:(Int)->Unit, onFinish:()->Unit,
                                    scope: CoroutineScope = GlobalScope
    ): Job {
        return flow{
            for (i in total downTo 0){
                emit(i)
                delay(1000)
            }
        }.flowOn(Dispatchers.IO)
            .onCompletion { onFinish.invoke() }
            .onEach { onTick.invoke(it) }
            .launchIn(scope)
    }


    @Throws(IOException::class)
    fun saveBitmapToCache(bitmap: Bitmap, parent:File,name:String):String {


        val file = File("${parent.path}/$name")

        if (file.exists()){
            file.delete()
        }

        val out: FileOutputStream
        try {
            out = FileOutputStream(file)
            if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)) {
                out.flush()
                out.close()
            }
        } catch (e: FileNotFoundException) {
            e.printStackTrace()
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return file.path
    }


    fun saveVideoToDCIM(context:Context,path:String,name:String,onFinish:()->Unit,onFail:()->Unit){

        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
            copyVideoToDCIM2(context,path,name,onFinish)

        }else{
            copyVideoToDCIM(context, path, name, onFinish, onFail)
        }
    }

    fun copyVideoToDCIM(context:Context,path:String,name:String,onFinish:()->Unit,onFail:()->Unit){
        val photoPath = Environment.DIRECTORY_DCIM + "/Camera"
        val contentValues = ContentValues().apply {
            put(MediaStore.MediaColumns.DISPLAY_NAME, name)
            put(MediaStore.Video.Media.MIME_TYPE, "video/mp4")
            put(MediaStore.MediaColumns.RELATIVE_PATH, photoPath)//保存路径
        }

        //9.0以及之前版本（测速试试10版本)
        /*val contentValues = ContentValues().apply {
            put("_display_name", File(path).name)
            put("mime_type", "video/mp4")
            put("_data", photoPath)//保存路径
        }*/

        val contentResolver = context.contentResolver
        val uri = contentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues)

        var outPutChannel: FileChannel?=null
        var inPutChannel: FileChannel?=null
        try {
            outPutChannel = ( contentResolver.openOutputStream(uri!!) as FileOutputStream).channel
            inPutChannel = FileInputStream(File(path)).channel

            inPutChannel.transferTo(0,inPutChannel.size(),outPutChannel)

            onFinish()


        }catch (e: IOException){
            e.printStackTrace()
            onFail()
        }finally {
            try {
                inPutChannel?.close()
                outPutChannel?.close()
            }catch (e: IOException){
                e.printStackTrace()
            }
        }

        context.sendBroadcast(
            Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri)
        )
//        File(path).delete()
    }


    //9.0以及之前存储视频方式 需要存储权限
    fun copyVideoToDCIM2(context:Context,path:String,name:String,onFinish:()->Unit){
//        val localContentValues =  ContentValues()
//        localContentValues.put("_display_name", name);
//        localContentValues.put("mime_type", "video/mp4");
//        localContentValues.put("_data", path);

        //9.0 往前的版本
        val file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).absoluteFile
        val resultPath = file.path + "/Camera/" + System.currentTimeMillis() + "$name.mp4"
//        val resultPath = file.path + "/Camera/" + System.currentTimeMillis() + "snake_video.mp4"

       val outChannel = RandomAccessFile(resultPath, "rwd").channel
        val `in`: FileInputStream = FileInputStream(path)
       val inChannel = `in`.channel
        inChannel.transferTo(0, inChannel.size(), outChannel)
        inChannel.close()
        outChannel.close()


        val localContentValues =  ContentValues()
        localContentValues.put("_display_name", File(resultPath).name);
        localContentValues.put("mime_type", "video/mp4");
        localContentValues.put("_data", resultPath)
        val contentResolver = context.contentResolver
        val uri = contentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, localContentValues)
        context.sendBroadcast(
            Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri)
        )
    }


    fun stringForTime(timeMs: Long): String? {
        val totalSeconds = timeMs / 1000
        val seconds = totalSeconds % 60
        val minutes = totalSeconds / 60 % 60
        val hours = totalSeconds / 3600
        return Formatter().format("%02d:%02d:%02d", hours, minutes, seconds).toString()
    }


    @TargetApi(Build.VERSION_CODES.N)
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    fun changeFlashLight(context: Context,openOrClose: Boolean) {
        //判断API是否大于24（安卓7.0系统对应的API）
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            try {
                //获取CameraManager
                val mCameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
                //获取当前手机所有摄像头设备ID
                val ids = mCameraManager.cameraIdList
                for (id in ids) {
                    val c = mCameraManager.getCameraCharacteristics(id!!)
                    //查询该摄像头组件是否包含闪光灯
                    val flashAvailable = c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE)
                    val lensFacing = c.get(CameraCharacteristics.LENS_FACING)
                    if(flashAvailable != null && flashAvailable && lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_BACK){
                        mCameraManager.setTorchMode(id, openOrClose)
                    }
                    /*if (flashAvailable != null && flashAvailable && lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_BACK) {
                        //打开或关闭手电筒
                        mCameraManager.setTorchMode(id, openOrClose)
                    }*/
                }
            } catch (e: CameraAccessException) {
                e.printStackTrace()
            }
        }
    }


}

/**
 * @param interval 单位毫秒，用于定时器延迟时间开启，例如：interval = 5000，则是5秒后才会开始倒计时
 * @param duration 单位毫秒，用户每次定时任务间隔时长执行1次，例如 duration = 1000，则每间隔1秒执行1次
 * @param totalTime 单位毫秒,用于定时器执行的总时长，
 *        如果为空的话，会一直在运行，直到手动调用cancel 方法，或者所在协程声明周期结束 而结束
 * @onNext(count) ,返回每次执行的次数
 * @onFinish() 任务正常执行完成
 */
fun CoroutineScope.startTime(
    interval:Long? = 0,
    duration:Long,
    totalTime:Long? = null,
    onNext:(Int)->Unit,
    onFinish:(()->Unit)? = null
):Job{
    if (duration<=0){
        throw IllegalArgumentException("间隔时间必须大于0")
    }
    return this.launch {
        interval?.let { _interval->
            if (_interval>0){
                delay(_interval)
            }
        }

        var isStart = true
        var runAllTotalTime:Long = 0
        var count = 0
        while (isStart){
            if (totalTime!= null && totalTime>0 && runAllTotalTime>= totalTime){
                isStart = false
                onFinish?.invoke()
            }else{
                delay(duration)
                runAllTotalTime+=duration
                count+=1
                onNext.invoke(count)
            }
        }
    }









}